package com.icongyou.enterprise.talent_analysis.service.support;

import com.icongyou.enterprise.talent_analysis.entity.template.TemplateDimension;
import com.icongyou.enterprise.talent_analysis.entity.template.TemplateMetricMapping;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class TemplateDimensionAutoFiller {

    private static final String DIM_TECH = "TECH";
    private static final String DIM_PROB = "PROBLEM";
    private static final String DIM_LEARN = "LEARN";
    private static final String DIM_TEAM = "TEAM";
    private static final String DIM_COMM = "COMM";
    private static final String DIM_EXEC = "EXEC";

    private Map<String, TemplateDimension> presetByCode;
    private Map<String, TemplateDimension> presetByName;

    public TemplateDimensionAutoFiller() {
        List<TemplateDimension> defaults = buildDefaultDimensions();
        presetByCode = defaults.stream()
            .collect(Collectors.toMap(TemplateDimension::getCode, Function.identity()));
        presetByName = defaults.stream()
            .collect(Collectors.toMap(dim -> dim.getName().toLowerCase(), Function.identity()));
    }

    public void fillMissingMetrics(List<TemplateDimension> dimensions) {
        if (dimensions == null) {
            return;
        }
        for (TemplateDimension dim : dimensions) {
            TemplateDimension preset = resolvePreset(dim);
            if (preset == null) {
                continue;
            }
            if (dim.getMetrics() == null || dim.getMetrics().isEmpty()) {
                if (preset.getMetrics() != null) {
                    dim.setMetrics(cloneMetrics(preset.getMetrics()));
                }
            }
            if (dim.getWeight() == null && preset.getWeight() != null) {
                dim.setWeight(preset.getWeight());
            }
        }
    }

    public List<TemplateDimension> defaultTemplate() {
        return buildDefaultDimensions();
    }

    private List<TemplateDimension> buildDefaultDimensions() {
        List<TemplateDimension> list = new ArrayList<>();
        list.add(buildDimension(DIM_TECH, "技术能力", "课程和作业成绩", Arrays.asList(
                metric("avg_course_score", 0.6, "direct", "course_students.score", "SELECT AVG(cs.score) FROM course_students cs WHERE cs.student_id = #{studentId}"),
                metric("avg_assignment_score", 0.4, "direct", "grades.final_score", "SELECT AVG(g.final_score) FROM grades g JOIN submissions s ON g.submission_id=s.submission_id WHERE s.student_id=#{studentId}")
        )));
        list.add(buildDimension(DIM_PROB, "问题解决", "作业通过与反馈", Arrays.asList(
            metric("assignment_pass_rate", 0.6, "ratio", "grades.final_score", "SELECT CASE WHEN COUNT(*)=0 THEN NULL ELSE SUM(CASE WHEN g.final_score >= a.full_score * #{passThreshold} THEN 1 ELSE 0 END)/COUNT(*) END FROM grades g JOIN submissions s ON g.submission_id = s.submission_id JOIN assignments a ON s.assignment_id = a.assignment_id WHERE s.student_id = #{studentId}"),
            metric("submission_like_index", 0.4, "capped_ratio", "submissions.like_count", "SELECT AVG(s.like_count + s.favorite_count) FROM submissions s WHERE s.student_id=#{studentId}")
        )));
        list.add(buildDimension(DIM_LEARN, "学习能力", "完成率与学习效率", Arrays.asList(
            metric("course_completion_rate", 0.5, "ratio", "course_progress.completed", "SELECT CASE WHEN SUM(cp.completed_tasks + cp.pending_tasks)=0 THEN NULL ELSE SUM(cp.completed_tasks)/NULLIF(SUM(cp.completed_tasks + cp.pending_tasks),0) END FROM course_progress cp WHERE cp.student_id=#{studentId}"),
            metric("learning_speed_index", 0.3, "ratio", "assignments.expected_duration", "SELECT AVG(a.expected_duration / NULLIF(s.actual_duration,0)) FROM submissions s JOIN assignments a ON s.assignment_id=a.assignment_id WHERE s.student_id=#{studentId} AND s.actual_duration IS NOT NULL"),
            metric("rework_rate_inverse", 0.2, "ratio", "submissions.count", "SELECT CASE WHEN t.total_cnt=0 THEN NULL ELSE (1 - t.multi_cnt / t.total_cnt) END FROM (SELECT COUNT(DISTINCT s.assignment_id) AS total_cnt, SUM(CASE WHEN sub.cnt>1 THEN 1 ELSE 0 END) AS multi_cnt FROM submissions s JOIN (SELECT assignment_id, student_id, COUNT(*) AS cnt FROM submissions WHERE student_id=#{studentId} GROUP BY assignment_id, student_id) sub ON sub.assignment_id = s.assignment_id AND sub.student_id = s.student_id WHERE s.student_id=#{studentId}) t")
        )));
        list.add(buildDimension(DIM_TEAM, "协作能力", "团队贡献与团队成绩", Arrays.asList(
                metric("contribution_rate_avg", 0.5, "ratio", "submissions.contribution_rate", "SELECT AVG(jt.rate) FROM submissions s, JSON_TABLE(s.contribution_rate, '$[*]' COLUMNS(studentId VARCHAR(36) PATH '$.studentId', rate DECIMAL(5,2) PATH '$.rate')) AS jt WHERE jt.studentId=#{studentId} AND s.team_id IS NOT NULL"),
                metric("avg_team_score", 0.5, "direct", "teams.current_score", "SELECT AVG(t.current_score) FROM teams t JOIN team_members tm ON t.team_id=tm.team_id WHERE tm.student_id=#{studentId}")
        )));
        list.add(buildDimension(DIM_COMM, "沟通能力", "教师反馈与讨论", Arrays.asList(
            metric("teacher_comment_rate", 0.7, "ratio", "grades.text_comment", "SELECT CASE WHEN COUNT(*)=0 THEN NULL ELSE SUM(CASE WHEN g.text_comment IS NOT NULL AND TRIM(g.text_comment)!='' THEN 1 ELSE 0 END)/COUNT(*) END FROM grades g JOIN submissions s ON g.submission_id=s.submission_id WHERE s.student_id=#{studentId}"),
                metric("discussion_count", 0.3, "count_capped", "discussion_records", "SELECT COUNT(*) FROM discussion_records d WHERE d.student_id=#{studentId}")
        )));
        list.add(buildDimension(DIM_EXEC, "执行能力", "及时提交与延期", Arrays.asList(
            metric("on_time_submission_rate", 0.7, "ratio", "submissions.is_late", "SELECT CASE WHEN COUNT(*)=0 THEN NULL ELSE SUM(CASE WHEN s.is_late = 0 THEN 1 ELSE 0 END)/COUNT(*) END FROM submissions s WHERE s.student_id=#{studentId}"),
            metric("deadline_miss_inverse", 0.3, "ratio", "assignments.end_time", "SELECT CASE WHEN COUNT(*)=0 THEN NULL ELSE (1 - AVG(CASE WHEN s.is_late=1 THEN GREATEST(TIMESTAMPDIFF(DAY, a.end_time, s.submission_time),0) ELSE 0 END)/NULLIF(#{maxLateDays},0)) END FROM submissions s JOIN assignments a ON s.assignment_id=a.assignment_id WHERE s.student_id=#{studentId}")
        )));
        return list;
    }

    private TemplateDimension buildDimension(String code, String name, String description, List<TemplateMetricMapping> metrics) {
        TemplateDimension dim = new TemplateDimension();
        dim.setCode(code);
        dim.setName(name);
        dim.setDescription(description);
        dim.setWeight(1.0);
        dim.setMetrics(metrics);
        return dim;
    }

    private TemplateMetricMapping metric(String key, double weight, String normalization, String source, String sql) {
        TemplateMetricMapping mapping = new TemplateMetricMapping();
        mapping.setMetricKey(key);
        mapping.setWeight(weight);
        mapping.setNormalization(normalization);
        mapping.setSource(source);
        mapping.setSql(sql);
        return mapping;
    }

    private TemplateDimension resolvePreset(TemplateDimension dim) {
        if (dim == null) {
            return null;
        }
        TemplateDimension preset = dim.getCode() != null ? presetByCode.get(dim.getCode()) : null;
        if (preset == null && dim.getName() != null) {
            preset = presetByName.get(dim.getName().toLowerCase());
        }
        return preset;
    }

    private List<TemplateMetricMapping> cloneMetrics(List<TemplateMetricMapping> source) {
        List<TemplateMetricMapping> copies = new ArrayList<>();
        for (TemplateMetricMapping mapping : source) {
            copies.add(mapping.clone());
        }
        return copies;
    }
}
